作者Beier Luo应该是一个华裔,现居澳大利亚悉尼,目前专注于BeekAI,他的youtube视频里面讲解了一些react hook form的实现原理,我准备好好学习一下,因为无论是哪个框架,form的场景我感觉是最复杂的,学了绝对有好处。
RHF 的核心设计目标是:最少的 re-renders、最大化性能,以及更轻量、更直接地管理表单状态。官方也在其 “Design and philosophy” 一栏里提到了:
“form state subscription model through the proxy” + “avoiding unnecessary computation” + “isolating component re-rendering when required” 下面我拆解几个关键点:
在传统的 React 表单处理方式中,你可能会为每个 input 建立 value 和 onChange,把值存在 state 中。这样每次用户输入就会触发 React 重新 render。RHF 则改变了这种思路:
useForm() 钩子,返回 register, handleSubmit, formState, … 等。{...register("fieldName", { required: true })},RHF 会把该 input 的 DOM ref、onChange、onBlur、name 等属性 “注册” 进去。这样输入变更时,它不是走 React state 更新整个组件,而是通过 ref + internal subscription 机制去追踪变化。RHF 内部用了“订阅”机制,也就是组件只订阅它真正关心的状态(比如 errors、dirtyFields、touchedFields 等)。这样当一个字段更新,但你并没有渲染那个字段错误状态时,不会导致整个 form 重新 render。官方提到“form state subscription model through the proxy”。 这样的模型相比 “每次 value 改都 setState → 整个组件重渲染” 要优很多,性能上更友好,尤其在大型或复杂表单中。
RHF 本身支持通过 register("name", { required: true, pattern: … }) 这种方式直接利用输入的规则。
此外,它也很好地支持通过 schema 验证库(比如 Zod、Yup)来做统一验证。
这种设计让验证逻辑更集中、可维护性更好。
RHF 推崇非受控组件(uncontrolled),即直接操作 DOM ref 来获取值,而不是每次 change 都更新 React state。但现实中很多 UI 库(如 MUI、AntD、react-select)都是受控组件。为此,RHF 提供了 Controller 组件,你可以用它包裹这些受控组件,从而让它们也能接入 RHF 的流程。
例如:
51<Controller2 name="selectField"3 control={control}4 render={({ field }) => <Select {field} options={…} />}5/>因为使用 ref 和订阅机制,以及尽可能少用 React state来跟踪每个字段变化,RHF 通常能比一些传统表单库(比如 Formik)在大型或频繁输入的表单中性能更好。freeCodeCamp 的文章也指出:“The number of re-renders in the application is smaller compared to the alternatives because it uses refs instead of state.” freecodecamp.org 另外,defaultValues、watch、setValue 这些 API也支持更灵活的场景。官方的 “Design and philosophy” 一节也提到“avoid unnecessary computation”这一点。
可以这样总结:
register 注册到 RHF 内部管理,RHF 管理 value、onBlur、onChange、validation 规则。Controller 接入。